package com.hb.common.util;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.codec.Rot;
import cn.hutool.core.util.ZipUtil;
import com.hb.common.constant.Config;
import com.hb.common.exception.DbBackupException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.zip.ZipInputStream;

/**
 * 公共工具类
 */
public class CommonUtil {

    private static final Logger log = LoggerFactory.getLogger(CommonUtil.class);

    /**
     * 检查指定路径是否存在，如果不存在则创建该目录。
     *
     * @param path 要检查的路径
     * @return 如果目录存在或成功创建，则返回true；否则返回false
     */
    public static boolean validateOrCreateDirectory(String path) {
        File directory = new File(path);

        // 检查目录是否存在
        if (directory.exists()) {
            // 目录存在，检查是否为目录
            return directory.isDirectory();
        } else {
            // 目录不存在，尝试创建目录
            return directory.mkdirs();
        }
    }

    /**
     * 检查指定目录中的文件数量，如果超出最大文件数量，则删除最旧的文件。
     *
     * @param directoryPath 目录路径
     * @param maxFiles      最大文件数量
     */
    public static void manageFiles(String directoryPath, int maxFiles) throws DbBackupException {
        File directory = new File(directoryPath);

        if (!directory.exists() || !directory.isDirectory()) {
            throw new DbBackupException("目录不存在或不是一个目录：" + directoryPath);
        }

        File[] files = directory.listFiles((dir, name) -> name.toLowerCase().endsWith(".sql") || name.toLowerCase().endsWith(".bak"));
        if (files == null) {
            throw new DbBackupException("无法列出目录中的文件：" + directoryPath);
        }

        // 检查文件数量是否超出限制
        if (files.length > maxFiles) {
            // 按最后修改时间排序文件，最旧的文件排在前面
            Arrays.sort(files, Comparator.comparingLong(File::lastModified));

            // 计算需要删除的文件数量
            int filesToDelete = files.length - maxFiles;

            // 删除最旧的文件
            for (int i = 0; i < filesToDelete; i++) {
                if (!files[i].delete()) {
                    throw new DbBackupException("无法删除历史文件：" + files[i].getName());
                }
            }
        }
    }

    /**
     * 将文件大小从 Byte 动态转换为适当的单位并格式化输出。
     *
     * @param sizeInBytes 文件大小，单位为 Byte
     * @return 格式化后的文件大小字符串
     */
    public static String formatFileSize(long sizeInBytes) {
        // 处理特殊情况
        if (sizeInBytes <= 0) return "0B";

        String[] units = {"B", "KB", "MB", "GB", "TB", "PB", "EB"};

        // 动态选择合适的单位
        int unitIndex = (int) (Math.log10(sizeInBytes) / Math.log10(1024));
        double size = sizeInBytes / Math.pow(1024, unitIndex);

        // 格式化输出
        return String.format("%.2f%s", size, units[unitIndex]);
    }

    /**
     * 解压数据库程序
     *
     * @param zipPath     压缩包文件路径
     * @param programPath 解压到目录
     */
    public static void unzipDbProgram(String zipPath, String programPath) {
        File runPathFile = new File(programPath);
        try (FileInputStream inputStream = new FileInputStream(zipPath)) {
            ZipUtil.unzip(new ZipInputStream(inputStream), runPathFile);
            runPermissions(programPath);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    /**
     * 解压数据库程序
     *
     * @param inputStream 文件流
     * @param programPath 解压到目录
     */
    public static void unzipDbProgram(InputStream inputStream, String programPath) {
        File runPathFile = new File(programPath);
        try {
            ZipUtil.unzip(new ZipInputStream(inputStream), runPathFile);
            runPermissions(programPath);
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                log.error(e.getMessage());
            }
        }
    }

    /**
     * 授予目录运行权限
     */
    public static void runPermissions(String programPath) {
        //如果是linux或mac授权允许运行权限
        if (System.getProperty("os.name").toLowerCase().contains(Config.LINUX)
                || System.getProperty("os.name").toLowerCase().contains(Config.MAC)) {
            try {
                Runtime.getRuntime().exec("chmod -R 777 " + programPath);
            } catch (IOException e) {
                log.error(e.getMessage());
            }
        }
    }

    /**
     * 创建指定路径和名称的文件
     *
     * @param filePath 文件路径
     * @param fileName 文件名称
     */
    public static void createFile(String filePath, String fileName) throws DbBackupException {
        // 创建File对象
        File file = new File(filePath + File.separator + fileName);

        // 检查目录是否存在，如果不存在则创建目录
        File directory = new File(filePath);
        if (!directory.exists()) {
            directory.mkdirs();
        }

        // 创建文件
        try {
            file.createNewFile();
        } catch (IOException e) {
            throw new DbBackupException(e);
        }
    }

    /**
     * 密码加密
     */
    public static String encryptPassword(String password) {
        // base64加密
        String base64 = Base64.encode(password);
        // 回转13位加密
        return Rot.encode13(base64);
    }

    /**
     * 密码解密
     */
    public static String decryptPassword(String password) {
        // 回转13位解密
        String decode13 = Rot.decode13(password);
        // base64解密
        return Base64.decodeStr(decode13);
    }
}
